home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
linux
/
tools
/
gtar10.lha
/
tar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-09
|
32KB
|
1,346 lines
/* Tar -- a tape archiver.
Copyright (C) 1988 Free Software Foundation
GNU tar is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GNU tar General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GNU tar,
but only under the conditions described in the GNU tar General Public
License. A copy of this license is supposed to have been given to you
along with GNU tar so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GNU tar, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/*
* A tar (tape archiver) program.
*
* Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
*
* @(#)tar.c 1.34 11/6/87 - gnu
*/
#include <stdio.h>
#include <sys/types.h> /* Needed for typedefs in tar.h */
#include <sys/stat.h> /* JF */
#include "getopt.h"
#include "regex.h"
#ifdef USG
#define rindex strrchr
#endif
#ifdef BSD42
#include <sys/dir.h>
#else
#ifdef __MSDOS__
#include "msd_dir.h"
#else
#ifdef USG
#ifdef NDIR
#include <ndir.h>
#else
#include <dirent.h>
#endif
#ifndef DIRECT
#define direct dirent
#endif
#define DP_NAMELEN(x) strlen((x)->d_name)
#else
/*
* FIXME: On other systems there is no standard place for the header file
* for the portable directory access routines. Change the #include line
* below to bring it in from wherever it is.
*/
#include "ndir.h"
#endif
#endif
#endif
#ifndef DP_NAMELEN
#define DP_NAMELEN(x) (x)->d_namlen
#endif
#ifndef __STDC__
extern char *malloc();
extern char *getenv();
extern char *strncpy();
extern char *index();
extern char *strcpy(); /* JF */
extern char *strcat(); /* JF */
#endif
extern char *optarg; /* Pointer to argument */
extern int optind; /* Global argv index from getopt */
extern char *ck_malloc();
extern char *ck_realloc();
/*
* The following causes "tar.h" to produce definitions of all the
* global variables, rather than just "extern" declarations of them.
*/
#define TAR_EXTERN /**/
#include "tar.h"
/*
* We should use a conversion routine that does reasonable error
* checking -- atoi doesn't. For now, punt. FIXME.
*/
#define intconv atoi
extern int getoldopt();
extern void read_and();
extern void list_archive();
extern void extract_archive();
extern void diff_archive();
extern void create_archive();
extern void update_archive();
extern void junk_archive();
/* JF */
extern time_t get_date();
time_t new_time;
static FILE *namef; /* File to read names from */
static char **n_argv; /* Argv used by name routines */
static int n_argc; /* Argc used by name routines */
static char **n_ind; /* Store an array of names */
static int n_indalloc; /* How big is the array? */
static int n_indused; /* How many entries does it have? */
static int n_indscan; /* How many of the entries have we scanned? */
int f_max_namelen = 0;
extern FILE *msg_file;
void describe();
void options();
#ifndef S_IFLNK
#define lstat stat
#endif
#ifndef DEFBLOCKING
#define DEFBLOCKING 20
#endif
#ifndef DEF_AR_FILE
#define DEF_AR_FILE "tar.out"
#endif
/* For long options that unconditionally set a single flag, we have getopt
do it. For the others, we share the code for the equivalent short
named option, the name of which is stored in the otherwise-unused `val'
field of the `struct option'; for long options that have no equivalent
short option, we use nongraphic characters as pseudo short option
characters, starting (for no particular reason) with character 10. */
struct option long_options[] =
{
{"create", 0, 0, 'c'},
{"append", 0, 0, 'r'},
{"extract", 0, 0, 'x'},
{"get", 0, 0, 'x'},
{"list", 0, 0, 't'},
{"update", 0, 0, 'u'},
{"catenate", 0, 0, 'A'},
{"concatenate", 0, 0, 'A'},
{"compare", 0, 0, 'd'},
{"diff", 0, 0, 'd'},
{"delete", 0, 0, 14},
{"help", 0, 0, 12},
{"directory", 1, 0, 'C'},
{"record-number", 0, &f_sayblock, 1},
{"files-from", 1, 0, 'T'},
{"label", 1, 0, 'V'},
{"exclude-from", 1, 0, 'X'},
{"exclude", 1, 0, 15},
{"file", 1, 0, 'f'},
{"block-size", 1, 0, 'b'},
{"version", 0, 0, 11},
{"verbose", 0, 0, 'v'},
{"totals", 0, &f_totals, 1},
{"read-full-blocks", 0, &f_reblock, 1},
{"starting-file", 1, 0, 'K'},
{"to-stdout", 0, &f_exstdout, 1},
{"ignore-zeros", 0, &f_ignorez, 1},
{"keep-old-files", 0, 0, 'k'},
{"uncompress", 0, &f_compress, 1},
{"same-permissions", 0, &f_use_protection, 1},
{"preserve-permissions",0, &f_use_protection, 1},
{"modification-time", 0, &f_modified, 1},
{"preserve", 0, 0, 10},
{"same-order", 0, &f_sorted_names, 1},
{"same-owner", 0, &f_do_chown, 1},
{"preserve-order", 0, &f_sorted_names, 1},
#ifdef amigados
{"amiga-perms", 0, 0, 'a'},
#endif
{"max-namelen", 1, 0, 'e'},
{"newer", 1, 0, 'N'},
{"after-date", 1, 0, 'N'},
{"newer-mtime", 1, 0, 13},
{"incremental", 0, 0, 'G'},
{"listed-incremental", 1, 0, 'g'},
{"multi-volume", 0, &f_multivol, 1},
{"info-script", 1, &f_run_script_at_end, 1},
{"absolute-paths", 0, &f_absolute_paths, 1},
{"interactive", 0, &f_confirm, 1},
{"confirmation", 0, &f_confirm, 1},
{"verify", 0, &f_verify, 1},
{"dereference", 0, &f_follow_links, 1},
{"one-file-system", 0, &f_local_filesys, 1},
{"old-archive", 0, 0, 'o'},
{"portability", 0, 0, 'o'},
{"compress", 0, &f_compress, 1},
{"compress-block", 0, &f_compress, 2},
{"sparse", 0, &f_sparse_files, 1},
{"tape-length", 1, 0, 'L'},
{0, 0, 0, 0}
};
/*
* Main routine for tar.
*/
main(argc, argv)
int argc;
char **argv;
{
extern char version_string[];
tar = argv[0]; /* JF: was "tar" Set program name */
errors = 0;
options(argc, argv);
if(!n_argv)
name_init(argc, argv);
switch(cmd_mode) {
case CMD_CAT:
case CMD_UPDATE:
case CMD_APPEND:
update_archive();
break;
case CMD_DELETE:
junk_archive();
break;
case CMD_CREATE:
create_archive();
if (f_totals)
fprintf (stderr, "Total bytes written: %d\n", tot_written);
break;
case CMD_EXTRACT:
if (f_volhdr) {
char *err;
label_pattern = (struct re_pattern_buffer *)
ck_malloc (sizeof *label_pattern);
err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
label_pattern);
if (err) {
fprintf (stderr,"Bad regular expression: %s\n",
err);
errors++;
break;
}
}
extr_init();
read_and(extract_archive);
break;
case CMD_LIST:
if (f_volhdr) {
char *err;
label_pattern = (struct re_pattern_buffer *)
ck_malloc (sizeof *label_pattern);
err = re_compile_pattern (f_volhdr, strlen (f_volhdr),
label_pattern);
if (err) {
fprintf (stderr,"Bad regular expression: %s\n",
err);
errors++;
break;
}
}
read_and(list_archive);
#if 0
if (!errors)
errors = different;
#endif
break;
case CMD_DIFF:
diff_init();
read_and(diff_archive);
break;
case CMD_VERSION:
fprintf(stderr,"%s\n",version_string);
break;
case CMD_NONE:
msg("you must specify exactly one of the r, c, t, x, or d options\n");
fprintf(stderr,"For more information, type ``%s +help''.\n",tar);
exit(EX_ARGSBAD);
}
exit(errors);
/* NOTREACHED */
}
/*
* Parse the options for tar.
*/
void
options(argc, argv)
int argc;
char **argv;
{
register int c; /* Option letter */
int ind = -1;
/* Set default option values */
blocking = DEFBLOCKING; /* From Makefile */
ar_file = getenv("TAPE"); /* From environment, or */
if (ar_file == 0)
ar_file = DEF_AR_FILE; /* From Makefile */
/* Parse options */
while ((c = getoldopt(argc, argv,
#ifndef amigados
"-01234567Ab:BcC:de:f:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
#else
"-01234567aAb:BcC:de:f:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
#endif
long_options, &ind)) != EOF) {
switch (c) {
c